package cn.accjiyun.authority;

import cn.accjiyun.qingcloud.QingCloudConstants;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;

/**
 * <p>签名工具类</p>
 * Created by jiyun on 2017/11/1.
 */
public class Signature {

    /**
     * 根据URL请求参数集合和签名方法，整理顺序转化为URL格式后签名
     * @param paramMap URL请求参数集合
     * @param algorithm 签名方法
     * @return 签名字符串
     */
    public static String getSignature(Map<String, String> paramMap, String algorithm) {
        String[] sortedKeys = paramMap.keySet().toArray(new String[] {});
        Arrays.sort(sortedKeys);
        final String SEPARATOR = "&";

        StringBuilder sbStringToSign = new StringBuilder();
        sbStringToSign.append(QingCloudConstants.requestMethod + "\n/iaas/\n");

        String signature = "";
        try {
            int count = 0;
            for (String key : sortedKeys) {
                if (count != 0) {
                    sbStringToSign.append(SEPARATOR);
                }
                sbStringToSign.append(StrConvertUrl(key)).append("=")
                        .append(StrConvertUrl(paramMap.get(key)));
                count++;
            }
            String strToSign = sbStringToSign.toString();
            Mac mac = Mac.getInstance(algorithm);
            mac.init(new SecretKeySpec(
                    QingCloudConstants.QY_SECRET_ACCESS_KEY.getBytes("UTF-8"),
                    algorithm));
            byte[] signData = mac.doFinal(strToSign.getBytes("UTF-8"));
            signature = new String(Base64.encodeBase64(signData));
        } catch (UnsupportedEncodingException | InvalidKeyException | NoSuchAlgorithmException e) {

        }
        return signature;
    }

    /**
     * 替换特殊字符
     * @param s 原字符串
     * @return 替换后的字符串
     * @throws UnsupportedEncodingException URL编码异常
     */
    private static String StrConvertUrl(String s) throws UnsupportedEncodingException {
        if (s == null || s.length() == 0) {
            return "";
        } else {
            return URLEncoder.encode(s, "UTF-8")
                    .replace("+", "%20")
                    .replace("*", "%2A")
                    .replace("%7E", "~");
        }
    }
}
